/**
 * @file   Utils.java
 * @author Soluciones Info Móviles SAC.
 * @date   Fri Aug 10 11:54:21 2007
 *
 */

package sim.utils;

import java.lang.Math;
import java.io.*;

/**
 * Implementar funciones de uso general.
 *
 *
 * @author Enrique J. Madrid M.
 * @version %I%, %I%
 * @since 1.0
 */
public final class Utils {
    
    // Lo siguiente puede dejar de ser util.
    public static final String CR = "\r"; // MacOS
    public static final String LF = "\n"; // Unix
    public static final String CRLF = "\r\n"; // Windows
    
    public static final int FMT_ZERO = 0x01; /**< Justifica a la derecha con 0 (cero) */
    public static final int FMT_SIGN = 0x02; /**< Imprimir con signo */
    public static final int FMT_PLUS = 0x04; /**< Mostrar el signo máx (+)*/
    public static final int FMT_SPAC = 0x08; /**< Usar spacio en lugar del signo máx (+) */
    public static final int FMT_LEFT = 0x10; /**< Justificar a la izquierda */
    public static final int FMT_OHEX = 0x20; /**< Utiliza los prefijos 0x y 0 (cero) para bases 16 y 8 */
    public static final int FMT_UPCA = 0x40; /**< Usar mayusculas para digitos de bases mayor 10*/
    
    /**
     * Representación en bytes de los números utilizados
     * desde la base 2 hasta la base 31 en minúsculas.
     * 0, 1, 2, ... 9, a, b, c ... z
     */
    public static final byte[] DIG_LOWER = {48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100,
    101, 102, 103, 102, 105, 106, 107, 108, 109, 110, 111,
    112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122};
    
    /**
     * Representación en bytes de los números utilizados
     * desde la base 2 hasta la base 31 en mayúsculas.
     * 0, 1, 2, ... 9, A, B, C ... Z
     */
    public static final byte[] DIG_UPPER = {48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69,
    69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
    84, 85, 86, 87, 88, 89, 90};
    
    
    /**
     * Valores de fin de linea utilizados por plataformas MacOS, Unix y Windows.
     * es decir CR, y LF (\r y \n)
     */
    public static final byte[] ENDOFLINE = {13, 10};
    
    /**
     * Operadores utilizados
     */
    public static final byte[] OPERATOR = { '*', '+', '-', '/' };
    
    /**
     * Comparadores utilizados.
     */
    public static final byte[] COMPARATOR = { '<', '=', '>' };
    
    /**
     * Tokens utilizados por la framework SIMP.
     */
    public static final byte    TOKEN_PIPE = 0;         // |
    public static final byte    TOKEN_COLON = 1;        // :
    public static final byte    TOKEN_UNDERSCORE = 2;   // _
    public static final byte    TOKEN_TILDE = 3;        // ~
    public static final byte    TOKEN_POUND = 4;        // #
    public static final byte    TOKEN_SEMICOLON = 5;    // ;
    public static final byte    TOKEN_EQUALS = 6;       // =
    public static final byte    TOKEN_POINT  = 7;       // .
    public static final byte    TOKEN_SPACE  = 8;       //
    public static final byte    TOKEN_SLASH  = 9;       // /
    public static final byte[]  TOKEN = { '|', ':', '_', '~', '#', ';', '=', '.', ' ', '/' };
    
    // Máx y mínimo valor para exponentes de un número double.
    public static final int DBL_MAX_EXP = 308;
    public static final int DBL_MIN_EXP = -307;
    
    public Utils() {
    }
    
    /**
     * Cambia de posición los bytes equidistantes.
     *
     * La función cambia la posición de los bytes equidistantes del inicio y fin
     * del sector de bytes a utilizar. Por ejemplo, si el sector de bytes contiene
     * 'abcdef', al aplicar la función, el contenido será 'fedcba'
     *
     * @param bytes Arreglo de bytes a utilizar.
     * @param start Primer byte del sector a utilizar.
     * @param count Número de bytes del sector a utilizar.
     */
    public static void memmirror(byte[] bytes, int start, int count) {
        byte tmp;
        int i;
        count = Math.min(count, bytes.length - start);
        for (i = 0; i < count /2; i++) {
            tmp = bytes[start + i];
            bytes[start + i] = bytes[start + count - 1 - i];
            bytes[start + count - 1 - i] = tmp;
        }
    }
    
    /**
     * Cambia de posición los bytes equidistantes.
     *
     * La función cambia la posición de los bytes equidistantes del primer sector de
     * bytes del arreglo a utilizar. Por ejemplo, si el sector de bytes contiene
     * 'abcdef', al aplicar la función, el contenido será 'fedcba'
     *
     * @param bytes Arreglo de bytes a utilizar.
     * @param count Número de bytes del sector a utilizar.
     */
    public static void memmirror(byte[] bytes, int count) {
        memmirror(bytes, 0, count);
    }
    
    /**
     * Cambia de posición los bytes equidistantes.
     *
     * La función cambia la posición de los bytes equidistantes en todo el arreglo
     * de bytes a utilizar. Por ejemplo, si el sector de bytes contiene 'abcdef',
     * al aplicar la función, el contenido será 'fedcba'
     *
     * @param bytes Arreglo de bytes a utilizar.
     */
    public static void memmirror(byte[] bytes) {
        memmirror(bytes, 0, bytes.length);
    }
    
    /**
     * Imprime la representación de un número entero con formato en un arreglo de bytes.
     *
     * @param bytes Arreglo de bytes destino.
     * @param start Primer byte del número representado.
     * @param count Longitud disponible, en bytes, para imprimir el el número representado.
     * @param num Numero entero que se desea representar.
     * @param base Base del número representado. Puede ser un valor entre 2 y 31.
     * @param precision Longitud de dígitos requerida del número representado, sin contar el signo ni
     *                  el ni otros caracteres de formato. Si un número tiene menos dígitos que este
     *                  valor, se completa con ceros, en caso contrario este valor es ignorado.
     * @param format Formato de la representación. Este es la súma lógica de los
     *               modificadores de formato Utils::FMT_ZERO, Utils::FMT_SIGN, Utils::FMT_PLUS,
     *               Utils::FMT_SPAC, Utils::FMT_LEFT, Utils::FMT_OHEX, Utils::FMT_UPCA.
     *
     * @return Devuelve la longitud en bytes de la representación. Si no se especifica el
     *         modificador Utils::FMT_LEFT, este valor es igual a count.
     */
    public static int fmtInteger(byte[] bytes, int start, int count, int num,
            int base, int precision, int format) {
        byte[] digits;
        boolean negative;
        byte b;
        int i;
        int ret;
        
        // Máxima longitud a utilizar
        count = Math.min(count, bytes.length - start);
        
        // Consistencia
        if ((count < 1) || (base < 2 || base > 32))
            return 0;
        
        // Conjunto de digitos a utilizar
        digits = ((format & FMT_UPCA) > 0) ? DIG_UPPER : DIG_LOWER;
        
        // Byte de relleno para justificación a la derecha
        b = ((format & FMT_ZERO) > 0) ? digits[0] : 32;
        
        // Valor absoluto del número
        negative = false;
        if (num < 0) {
            num = -num;
            negative = true;
        }
        
        // Bytes utilizados en la representación.
        ret = 0;
        // Bytes escritos en el arreglo
        i = 0;
        
        // Imprimimir el número en espejo
        if (num == 0)
            bytes[start + i++] = digits[0];
        else {
            while((i < count) && (num != 0)) {
                bytes[start + i++] = digits[num % base];
                num = num / base;
            }
        }
        
        // Añadir los bytes de precision
        while ((i < count) && (i < precision)) {
            bytes[start + i++] = digits[0];
        }
        
        // Utiliza los prefijos 0x y 0 (cero) para bases 16 y 8
        if ((i < count) && (format & FMT_OHEX) > 0) {
            if (base == 8)
                bytes[start + i++] = digits[0];
            else if(base == 16) {
                // Primero X por estar en espejo :-)
                bytes[start + i++] = digits[33];
                bytes[start + i++] = digits[0];
            }
        }
        
        // Incluir byte de signo
        if ((i < count) && ((format & FMT_SIGN) > 0)) {
            if (negative) {
                bytes[start + i++] = 45; // '-'
            } else if ((format & FMT_PLUS) > 0) {
                bytes[start + i++] = 43; // '+'
            } else if ((format & FMT_SPAC) > 0) {
                bytes[start + i++] = 32; // ' '
            }
        }
        
        // Añadir los bytes de justificación a la derecha
        if ((format & FMT_LEFT) == 0) {
            while ((i < count))
                bytes[start + i++] = b;
        }
        
        // Bytes utilizados en la representación
        ret = i;
        
        // Reflejar el número del espejo
        memmirror(bytes, start, i);
        
        // Añadir bytes de justificación a la izquierda
        if ((format & FMT_LEFT) > 0) {
            while ((i < count))
                bytes[start + i++] = 32;	// ' '
        }
        
        // Número de bytes utilizados en la representacion
        return ret;
    }
    
    /**
     * Imprime la representación de un número entero con formato en un arreglo de bytes.
     *
     * @param bytes Arreglo de bytes destino.
     * @param count Longitud disponible, en bytes, para imprimir el el número representado.
     * @param num Número entero que se desea representar.
     * @param base Base del número representado. Puede ser un valor entre 2 y 31.
     * @param precision Longitud de dígitos requerida del número representado, sin contar el signo ni
     *                  el ni otros caracteres de formato. Si un número tiene menos dígitos que este
     *                  valor, se completa con ceros, en caso contrario este valor es ignorado.
     * @param format Formato de la representación. Este es la súma lógica de los
     *               modificadores de formato Utils::FMT_ZERO, Utils::FMT_SIGN, Utils::FMT_PLUS,
     *               Utils::FMT_SPAC, Utils::FMT_LEFT, Utils::FMT_OHEX, Utils::FMT_UPCA.
     *
     * @return Devuelve la longitud en bytes de la representación. Si no se especifica el
     *         modificador Utils.FMT_LEFT, este valor es igual a count.
     */
    public static int fmtInteger(byte[] bytes, int count, int num,
            int base, int precision, int format) {
        return fmtInteger(bytes, 0, count, num, base, precision, format);
    }
    
    /**
     * Imprime la representación de un número entero con formato en un arreglo de bytes.
     *
     * @param bytes Arreglo de bytes destino.
     * @param num Número entero que se desea representar.
     * @param base Base del número representado. Puede ser un valor entre 2 y 31.
     * @param precision Longitud de dígitos requerida del número representado, sin contar el signo ni
     *                  el ni otros caracteres de formato. Si un número tiene menos dígitos que este
     *                  valor, se completa con ceros, en caso contrario este valor es ignorado.
     * @param format Formato de la representación. Este es la súma lógica de los
     *               modificadores de formato Utils::FMT_ZERO, Utils::FMT_SIGN, Utils::FMT_PLUS,
     *               Utils::FMT_SPAC, Utils::FMT_LEFT, Utils::FMT_OHEX, Utils::FMT_UPCA.
     *
     * @return Devuelve la longitud en bytes de la representación. Si no se especifica el
     *         modificador Utils.FMT_LEFT, este valor es igual a count.
     */
    public static int fmtInteger(byte[] bytes, int num, int base,
            int precision, int format) {
        return fmtInteger(bytes, 0, bytes.length, num, base, precision, format);
    }
    
    
    /**
     * Determina si un byte es un dígito.
     *
     * @param b Byte que representa un digito.
     * @param base Base a la que debe pertenecer el digito representado por 'b'.
     *
     * @return Si la función tiene éxito devuelve el valor decimal del dígito. en
     *         caso contrario devuelve -1.
     */
    public static int isDigit(byte b, int base) {
        
        // Si el byte es un número ...
        if ((b >= DIG_LOWER[0]) && (b <= DIG_LOWER[9])) {
            // probar que este dentro de la base
            if ((b - DIG_LOWER[0]) < base) {
                return (b - DIG_LOWER[0]);
            }
        } else if ((base > 10) && (base <= DIG_LOWER.length)) {
            // si es es un caracter ...
            // ... b puede estar en minúsculas
            if ((b >= DIG_LOWER[10]) && (b <= DIG_LOWER[base - 1])) {
                return ((b - DIG_LOWER[10]) + 10);
            }
            // ... b puede estar en mayúsculas
            if ((b >= DIG_UPPER[10]) && (b <= DIG_UPPER[base - 1])) {
                return ((b - DIG_UPPER[10]) + 10);
            }
        }
        
        return -1;
    }
    
    /**
     * Prueba si un byte corresponde a un dígito en base 10.
     *
     * @param b Byte a probar.
     *
     * @return Si es un dígito en base 10 devuelve true; en caso contrario
     *         devuelve false.
     */
    public static boolean isDigit(byte b) {
        return ((b >= DIG_LOWER[0]) && (b <= DIG_LOWER[9]));
    }
    
    /**
     * Prueba si un byte corresponde a un espación en blanco.
     *
     * @param b Byte a probar.
     *
     * @return Si es un espacion en blanco devuel true, caso contrario
     *         devuelve false.
     */
    public static boolean isSpace(byte b) {
        return (b == TOKEN[TOKEN_SPACE]);
    }
    
    /**
     * Convierte los bytes de una representación numérica a su valor decimal.
     *
     * La función convierte un flujo de bytes que contiene la represetación numérica
     * de un número a su valor decimal.
     *
     * @param bytes Arreglo de bytes que contiene la representacion del número.
     * @param start Primer byte de la representación
     * @param count Cantidad de bytes de la representación. Si un byte entre start y
     *              (start + count) no representa un dígito de la base. la conversión
     *              se detiene antes que count. Por ejemlo, para los bytes -523:Linux
     *              la función devuelve -523.
     *
     * @param base Base en que se encuentra representado el número.
     *
     * @return Devuelve el valor decimal de la representación del número.
     */
    public static int memtoul(final byte[] bytes, int start, int count, int base) {
        int ret;
        int i;
        int sign;
        int factor;
        
        if (count != 0) {
            // Consistencia (for Dummys)
            count = Math.min(count, bytes.length - start);
            
            ret = 0;
            i = 0;
            
            // Buscar signo
            sign = 1;
            if (memmem(OPERATOR, 1, 2, bytes, start, 1) > 0) {
                if (OPERATOR[2] == bytes[start]) {
                    sign = -1;
                }
                start++;
                count--;
            }
            
            // Buscar formato especial 0x en base 16 (para la otra version).
            
            // Contar los digitos que corresponden al número
            while((i < count) && (isDigit(bytes[start + i], base) > -1)) {
                i++;
            }
            
            // Calcular la suma decimal del desarrollo polinomial.
            factor = 1;
            while(i > 0) {
                ret += (isDigit(bytes[start + --i], base)*factor);
                factor *= base;
            }
            
            return sign*ret;
        }
        return 0;
    }
    
    /**
     * Convierte los bytes de una representación numérica a su valor decimal.
     *
     * La función convierte un flujo de bytes que contiene la represetación numérica
     * de un número a su valor decimal.
     *
     * @param bytes Arreglo de bytes que contiene la representacion del número.
     * @param start Primer byte de la representación
     * @param base Base en que se encuentra representado el número.
     *
     * @return Devuelve el valor decimal de la representación del número.
     */
    public static int memtoul(final byte[] bytes, int start, int base) {
        return memtoul(bytes, start, bytes.length - start, base);
    }
    
    /**
     * Convierte los bytes de una representación numérica a su valor decimal.
     *
     * La función convierte un flujo de bytes que contiene la represetación numérica
     * de un número a su valor decimal.
     *
     * @param bytes Arreglo de bytes que contiene la representacion del número.
     * @param base Base en que se encuentra representado el número.
     *
     * @return Devuelve el valor decimal de la representación del número.
     */
    public static int memtoul(final byte[] bytes, int base) {
        return memtoul(bytes, 0, bytes.length, base);
    }
    
    /**
     * Convierte los caracteres de una representación numérica a su valor decimal.
     *
     * @param number Cadena de caracteres que contiene la representacion del número.
     * @param base Base en que se encuentra representado el número.
     *
     * @return Devuelve el valor decimal de la representación del número.
     */
    public static int memtoul(final String number, int base) {
        return memtoul(number.getBytes(), base);
    }
    
    /**
     * Convierte los caracteres de una representación numérica a su valor double de punto flotante..
     *
     * @param bytes Arreglo de bytes que contiene la representacion del número.
     * @param start Primer byte de la representación
     * @param count Cantidad de bytes de la representación. Si un byte entre start y
     *              (start + count) no representa un dígito de la base. la conversión
     *              se detiene antes que count. Por ejemlo, para los bytes -2.3:Linux
     *              la función devuelve -2.3.
     *
     * @return Devuelve el valor double de punto flotante de la representación del número.
     */
    public static double memtod(final byte[] bytes, int start, int count) {
        double number;
        int exponent;
        int sign;
        double p10;
        int n;
        int integers;
        int decimals;
        int i;
        
        // Indice relativo a start (< count).
        i = 0;
        
        // Ingnorar espacios en blanco
        while ((i < count) && isSpace(bytes[start + i])) {
            i++;
        }
        
        // Detectar signo
        sign = 1;
        if (i < count) {
            switch(bytes[i]) {
                case '-': sign = -1;
                case '+': i++;
            }
        }
        
        number = 0.;
        exponent = 0;
        integers = 0;
        decimals = 0;
        
        // Digitos enteros
        while ((i < count) && isDigit(bytes[start + i])) {
            number = number * 10. + (bytes[i] - DIG_LOWER[0]);
            i++;
            integers++;
        }
        
        // Parte decimal
        if ((i < count) && (bytes[i] == '.')) {
            i++;
            while ((i < count) && isDigit(bytes[start + i])) {
                number = number * 10. + (bytes[start + i] - DIG_LOWER[0]);
                i++;
                integers++;
                decimals++;
            }
            exponent -= decimals;
        }
        
        if (integers == 0) {
            return 0.0;
        }
        
        // Aplicar signo
        number *= sign;
        
        
        // Parte exponencial
        if ((i < count) &&
                ((bytes[start + i] == 'e') || (bytes[start + i] == 'E'))) {
            
            i++;
            
            // Detectar signo de la parse exponecial
            sign = 1;
            if (i < count) {
                switch(bytes[start + i]) {
                    case '-': sign = -1;
                    case '+': i++;
                }
            }
            
            // Dígitos de parte exponecial
            n = 0;
            while ((i < count) && isDigit(bytes[start + i])) {
                n = n * 10 + (bytes[start + i] - DIG_LOWER[0]);
                i++;
            }
            
            exponent *= sign;
        }
        
        if (exponent < DBL_MIN_EXP) {
            return Double.MIN_VALUE;
        }
        
        if (exponent > DBL_MAX_EXP) {
            return Double.MAX_VALUE;
        }
        
        // Escalando el resultado
        p10 = 10.;
        n = exponent;
        if (n < 0) n = -n;
        while (n > 0) {
            if ((n & 1) > 0) {
                if (exponent < 0)
                    number /= p10;
                else
                    number *= p10;
            }
            n >>= 1;
            p10 *= p10;
        }
        
        return number;
    }
    
    /**
     * Convierte los caracteres de una representación numérica a su valor double de punto flotante..
     *
     * @param bytes Arreglo de bytes que contiene la representacion del número.
     * @param start Primer byte de la representación
     *
     * @return Devuelve el valor double de punto flotante de la representación del número.
     */
    public static double memtod(final byte[] bytes, int start) {
        return memtod(bytes, start, bytes.length - start);
    }
    
    /**
     * Convierte los caracteres de una representación numérica a su valor double de punto flotante..
     *
     * @param bytes Arreglo de bytes que contiene la representacion del número.
     *
     * @return Devuelve el valor double de punto flotante de la representación del número.
     */
    public static double memtod(final byte[] bytes) {
        return memtod(bytes, 0, bytes.length);
    }
    
    /**
     * Convierte los caracteres de una representación numérica a su valor double de punto flotante..
     *
     * @param number Cadena de caracteres que contiene la representacion del número.
     *
     * @return Devuelve el valor double de punto flotante de la representación del número.
     */
    public static double memtod(final String number) {
        return memtod(number.getBytes(), 0);
    }
    
    /**
     * Copia un byte sobre un sector de un arreglo de bytes.
     *
     * @param bytes Arreglo de bytes.
     * @param start Primer byte del sector a imprimir.
     * @param count Longitud del sector en bytes.
     * @param b byte utilizado.
     */
    public static void memset(byte[] bytes, int start, int count, byte b) {
        int i;
        int maxSet;
        maxSet = Math.min(bytes.length - start, count);
        for (i = start; i < maxSet + start; i++) {
            bytes[i] = b;
        }
    }
    
    /**
     * Copia un byte sobre un sector de un arreglo de bytes.
     *
     * @param bytes Arreglo de bytes.
     * @param count Longitud del sector en bytes.
     * @param b byte utilizado.
     */
    public static void memset(byte[] bytes, int count, byte b) {
        memset(bytes, 0, count, b);
    }
    
    /**
     * Copia un byte sobre un sector de un arreglo de bytes.
     *
     * @param bytes Arreglo de bytes.
     * @param b byte utilizado.
     */
    public static void memset(byte[] bytes, byte b) {
        memset(bytes, 0, 0, b);
    }
    
    
    /**
     * Mueve bytes de un arreglo a otro arreglo.
     *
     * El arreglo origen y destino puede ser el mismo.
     *
     * @param tgt Arreglo destino.
     * @param start_tgt Primer byte copiado hacia el arreglo destino.
     * @param src Arreglo origen.
     * @param start_src Primer byte copiado desde el arreglo origen.
     * @param count cantidad de bytes a mover.
     */
    public static void memmove(byte[] tgt, int start_tgt,
            byte[] src, int start_src,
            int count) {
        int maxMove;
        maxMove = Math.min(tgt.length - start_tgt, src.length - start_src);
        maxMove = Math.min(maxMove, count);
        if (maxMove > 0) {
            System.arraycopy(src, start_src, tgt, start_tgt, maxMove);
        }
    }
    
    /**
     * Mueve bytes en un mismo arreglo.
     *
     * @param buffer Arreglo origen y destino.
     * @param from Primer byte a mover.
     * @param to Posición del primer byte movido.
     * @param count cantidad de bytes a mover.
     */
    public static void memmove(byte[] buffer, int from, int to, int count) {
        Utils.memmove(buffer, to, buffer, from, count);
    }
    
    /**
     * Copia los bytes de un arreglo a otro arreglo.
     *
     * @param tgt Arreglo destino.
     * @param start_tgt Primer byte copiado hacia el arreglo destino.
     * @param src Arreglo origen.
     * @param start_src Primer byte copiado desde el arreglo origen.
     * @param count cantidad de bytes copiados.
     */
    public static void memcpy(byte[] tgt, int start_tgt,
            byte[] src, int start_src,
            int count) {
        Utils.memmove(tgt, start_tgt, src, start_src, count);
    }
    
    /**
     * Copia todos los bytes de un arreglo a otro arreglo.
     *
     * @param tgt Arreglo destino.
     * @param src Arreglo origen.
     */
    public static void memcpy(byte[] tgt, byte[] src) {
        memcpy(tgt, 0, src, 0, src.length);
    }
    
    /**
     * Busca la primera coincidencia de bytes en un arreglo de bytes.
     *
     * @param src Arreglo de bytes.
     * @param start_src Primer byte del arreglo que se compara.
     * @param length_src Rango de la busqueda sobre el arreglo, en bytes.
     * @param tok Bytes a buscar.
     * @param start_tok Primer byte de tok que debe comparar.
     * @param length_tok Longitud de bytes a partir de start_ok que se comparan.
     *
     * @return Devuelve el indice del primer byte de coincidencia sobre src.
     *         En caso contrario devuelve -1.
     */
    public static int memmem(final byte[] src, int start_src, int length_src,
            final byte[] tok, int start_tok, int length_tok) {
        int cp;
        int s1;
        int s2;
        int src_len;
        int tok_len;
        
        src_len = Math.min(src.length - start_src, length_src);
        tok_len = Math.min(tok.length - start_tok, length_tok);
        
        if (tok_len == 0) {
            return start_src;
        }
        
        cp = start_src;
        
        while (src_len - (cp - start_src) > 0) {
            s1 = cp;
            s2 = start_tok;
            
            while ((src_len - (s1 - start_src) > 0) &&
                    (tok_len - (s2 - start_tok) > 0) &&
                    (src[s1] == tok[s2])) {
                s1++;
                s2++;
            }
            
            if (tok_len - (s2 - start_tok) == 0) {
                return cp;
            }
            
            cp++;
        }
        
        return -1;
    }
    
    /**
     * Busca la primera coincidencia de bytes en un arreglo de bytes.
     *
     * @param src Arreglo de bytes.
     * @param start_src Primer byte del arreglo que se compara.
     * @param length_src Rango de la busqueda sobre el arreglo, en bytes.
     * @param tok Bytes a buscar.
     * @param length_tok Longitud de bytes que se debe comparar.
     *
     * @return Devuelve el indice del primer byte de coincidencia sobre src.
     *         En caso contrario devuelve -1.
     */
    public static int memmem(byte[] src, int start_src, int length_src,
            byte[] tok, int length_tok) {
        return Utils.memmem(src, start_src, length_src, tok, 0, length_tok);
    }
    
    /**
     * Busca la primera coincidencia de bytes en un arreglo de bytes.
     *
     * @param src Arreglo de bytes.
     * @param start_src Primer byte del arreglo que se compara.
     * @param length_src Rango de la busqueda sobre el arreglo, en bytes.
     * @param tok Bytes a buscar.
     *
     * @return Devuelve el indice del primer byte de coincidencia sobre src.
     *         En caso contrario devuelve -1.
     */
    public static int memmem(byte[] src, int start_src, int length_src, byte[] tok) {
        return Utils.memmem(src, start_src, length_src, tok, 0, tok.length);
    }
    
    /**
     * Busca la primera coincidencia de bytes en un arreglo de bytes.
     *
     * @param src Arreglo de bytes.
     * @param start_src Primer byte del arreglo que se compara.
     * @param tok Bytes a buscar.
     *
     * @return Devuelve el indice del primer byte de coincidencia sobre src.
     *         En caso contrario devuelve -1.
     */
    public static int memmem(byte[] src, int start_src, byte[] tok) {
        return Utils.memmem(src, start_src, (src.length - start_src), tok, 0, tok.length);
    }
    
    /**
     * Busca la primera coincidencia de bytes en un arreglo de bytes.
     *
     * @param src Arreglo de bytes.
     * @param tok Bytes a buscar.
     *
     * @return Devuelve el indice del primer byte de coincidencia sobre src.
     */
    public static int memmem(byte[] src, byte[] tok) {
        return Utils.memmem(src, 0, src.length, tok, 0, tok.length);
    }
    
    private static int _memncmp(final byte[] m1, int start_m1, int length_m1,
            final byte[] m2, int start_m2, int length_m2,
            int count) {
        // La siguiente condicional es lógica de comparación y no puede
        // omitirse.
        if ((length_m1 < 1) || (length_m2 < 1) || (count < 1)) {
            return 0;
        }
        
        // Límite de comparacion
        count = Math.min(count, length_m1);
        count = Math.min(count, length_m2);
        
        while ((--count > 0) && (m1[start_m1] == m2[start_m2])) {
            start_m1++;
            start_m2++;
        }
        
        return (m1[start_m1] - m2[start_m2]);
    }
    
    /**
     * Compara "count" bytes de los sectores de dos arreglos de bytes.
     *
     * @param m1 Primer arreglo de bytes a utilizar.
     * @param start_m1 Primer byte del primer sector.
     * @param length_m1 Longitud del primer sector.
     * @param m2 Segundo arreglo de bytes a utilizar.
     * @param start_m2 Primer byte del sengundo sector.
     * @param length_m2 Longitud del segundo sector.
     * @param count Cantidad de bytes a comparar de los dos sectores.
     *
     * @return Devuelve un valor menor que cero (< 0) si el sector de m1 es menor que
     *         que el sector de m2 en "count" bytes; un valor igual a cero (= 0) si
     *         el sector de m1 es igual al sector de m2 en "count" bytes; y un valor
     *         mayor que cero (> 0) si el sector de m1 es mayor que el sector de m2
     *         en en "count" bytes.
     */
    public static int memncmp(final byte[] m1, int start_m1, int length_m1,
            final byte[] m2, int start_m2, int length_m2,
            int count) {
        // Estabilidad (for dummys)
        // Lo siguiente puede omitirse si el programador es responsable.
        length_m1 = Math.min(length_m1, m1.length - start_m1);
        length_m2 = Math.min(length_m2, m2.length - start_m2);
        // Llamando al algoritmo genérico.
        return _memncmp(m1, start_m1, length_m1,
                m2, start_m2, length_m2,
                count);
    }
    
    /**
     * Compara "count" bytes de dos arreglos de bytes.
     *
     * @param m1 Primer arreglo de bytes a utilizar.
     * @param start_m1 Utilizar el primer arreglo desde esta posición.
     * @param m2 Segundo arreglo de bytes a utilizar.
     * @param start_m2 Utilizar el segundo arreglo desde esta posición.
     * @param count Cantidad de bytes a comparar de los dos arreglos.
     *
     * @return Devuelve un valor menor que cero (< 0) si el arreglo m1 es menor que
     *         que el arreglo m2 en "count" bytes; un valor igual a cero (= 0) si
     *         el arreglo m1 es igual al arreglo m2 en "count" bytes; y un valor
     *         mayor que cero (> 0) si el arreglo m1 es mayor que el arreglo m2
     *         en "count" bytes.
     */
    public static int memncmp(final byte[] m1, int start_m1,
            final byte[] m2, int start_m2,
            int count) {
        return memncmp(m1, start_m1, m1.length,
                m2, start_m2, m2.length,
                count);
    }
    
    /**
     * Compara "count" bytes de dos arreglos de bytes.
     *
     * @param m1 Primer arreglo de bytes a utilizar.
     * @param m2 Segundo arreglo de bytes a utilizar.
     * @param count Cantidad de bytes a comparar de los dos arreglos.
     *
     * @return Devuelve un valor menor que cero (< 0) si el arreglo m1 es menor que
     *         que el arreglo m2 en "count" bytes; un valor igual a cero (= 0) si
     *         el arreglo m1 es igual al arreglo m2 en "count" bytes; y un valor
     *         mayor que cero (> 0) si el arreglo m1 es mayor que el arreglo m2
     *         en "count" bytes.
     */
    public static int memncmp(final byte[] m1, final byte[] m2, int count) {
        return memncmp(m1, 0, m1.length,
                m2, 0, m2.length,
                count);
    }
    
    /**
     * Compara los sectores de dos arreglos de bytes.
     *
     * @param m1 Primer arreglo de bytes a utilizar.
     * @param start_m1 Primer byte del primer sector.
     * @param length_m1 Longitud del primer sector.
     * @param m2 Segundo arreglo de bytes a utilizar.
     * @param start_m2 Primer byte del sengundo sector.
     * @param length_m2 Longitud del segundo sector.
     *
     * @return Devuelve un valor menor que cero (< 0) si el sector de m1 es menor que
     *         que el sector de m2; un valor igual a cero (= 0) si el sector de m1 es
     *         igual al sector de m2; y un valord mayor que cero (> 0) si el sector
     *         de m1 es mayor que el sector de m2.
     */
    public static int memcmp(final byte[] m1, int start_m1, int length_m1,
            final byte[] m2, int start_m2, int length_m2) {
        // Estabilidad (for dummys)
        // Lo siguiente puede omitirse si el programador es responsable.
        length_m1 = Math.min(length_m1, m1.length - start_m1);
        length_m2 = Math.min(length_m2, m2.length - start_m2);
        // La siguiente condicional es lógica de comparación y no puede
        // omitirse.
        if ((length_m1 > 0) && (length_m2 > 0) && (length_m1 == length_m2)) {
            return _memncmp(m1, start_m1, length_m1,
                    m2, start_m2, length_m2,
                    length_m1);
        }
        return (length_m1 - length_m2);
    }
    
    /**
     * Compara dos arreglos de bytes.
     *
     * @param m1 Primer arreglo de bytes a utilizar.
     * @param start_m1 Utilizar el primer arreglo desde esta posición.
     * @param m2 Segundo arreglo de bytes a utilizar.
     * @param start_m2 Utilizar el segundo arreglo desde esta posición.
     *
     * @return Devuelve un valor menor que cero (< 0) si el arreglo m1 es menor que
     *         que el arreglo m2; un valor igual a cero (= 0) si el arreglo m1 es
     *         igual al arreglo m2; y un valor mayor que cero (> 0) si el arreglo
     *         m1 es mayor que el arreglo m2.
     */
    public static int memcmp(final byte[] m1, int start_m1,
            final byte[] m2, int start_m2) {
        return memcmp(m1, start_m1, m1.length,
                m2, start_m2, m2.length);
    }
    
    /**
     * Compara dos arreglos de bytes.
     *
     * @param m1 Primer arreglo de bytes a utilizar.
     * @param m2 Segundo arreglo de bytes a utilizar.
     *
     * @return Devuelve un valor menor que cero (< 0) si el arreglo m1 es menor que
     *         que el arreglo m2; un valor igual a cero (= 0) si el arreglo m1 es
     *         igual al arreglo m2; y un valor mayor que cero (> 0) si el arreglo
     *         m1 es mayor que el arreglo m2.
     */
    public static int memcmp(final byte[] m1, final byte[] m2) {
        return memcmp(m1, 0, m1.length,
                m2, 0, m2.length);
    }
    
    private static int _memnicmp(final byte[] m1, int start_m1, int length_m1,
            final byte[] m2, int start_m2, int length_m2,
            int count) {
        
        byte f, l;
        
        // La siguiente condicional es lógica de comparación y no puede
        // omitirse.
        if ((length_m1 < 1) || (length_m2 < 1) || (count < 1)) {
            return 0;
        }
        
        // Límite de comparacion
        count = Math.min(count, length_m1);
        count = Math.min(count, length_m2);
        
        do {
            f = m1[start_m1++];
            if ((f >= 'A') && (f <= 'Z')) {
                f -= ('A' - 'a');
            }
            l = m2[start_m2++];
            if ((l >= 'A') && (l <= 'Z')) {
                l -= ('A' - 'a');
            }
        } while ((--count > 0) && (f == l));
        
        return f - l;
    }
    
    /**
     * Compara "count" bytes de los sectores de dos arreglos de bytes, en forma insensitiva.
     *
     * @param m1 Primer arreglo de bytes a utilizar.
     * @param start_m1 Primer byte del primer sector.
     * @param length_m1 Longitud del primer sector.
     * @param m2 Segundo arreglo de bytes a utilizar.
     * @param start_m2 Primer byte del sengundo sector.
     * @param length_m2 Longitud del segundo sector.
     * @param count Cantidad de bytes a comparar de los dos sectores.
     *
     * @return Devuelve un valor menor que cero (< 0) si el sector de m1 es menor que
     *         que el sector de m2 en "count" bytes; un valor igual a cero (= 0) si
     *         el sector de m1 es igual al sector de m2 en "count" bytes; y un valor
     *         mayor que cero (> 0) si el sector de m1 es mayor que el sector de m2
     *         en "count" bytes.
     */
    public static int memnicmp(final byte[] m1, int start_m1, int length_m1,
            final byte[] m2, int start_m2, int length_m2,
            int count) {
        // Estabilidad (for dummys)
        // Lo siguiente puede omitirse si el programador es responsable.
        length_m1 = Math.min(length_m1, m1.length - start_m1);
        length_m2 = Math.min(length_m2, m2.length - start_m2);
        return _memnicmp(m1, start_m1, length_m1,
                m2, start_m2, length_m2,
                count);
    }
    
    /**
     * Compara "count" bytes de dos arreglos de bytes, en forma insensitiva.
     *
     * @param m1 Primer arreglo de bytes a utilizar.
     * @param start_m1 Utilizar el primer arreglo desde esta posición.
     * @param m2 Segundo arreglo de bytes a utilizar.
     * @param start_m2 Utilizar el segundo arreglo desde esta posición.
     * @param count Cantidad de bytes a comparar de los dos arreglos.
     *
     * @return Devuelve un valor menor que cero (< 0) si el arreglo m1 es menor que
     *         que el arreglo m2 en "count" bytes; un valor igual a cero (= 0) si
     *         el arreglo m1 es igual al arreglo m2 en "count" bytes; y un valor
     *         mayor que cero (> 0) si el arreglo m1 es mayor que el arreglo m2
     *         en "count" bytes.
     */
    public static int memnicmp(final byte[] m1, int start_m1,
            final byte[] m2, int start_m2,
            int count) {
        return memnicmp(m1, start_m1, m1.length - start_m1,
                m2, start_m2, m2.length - start_m2,
                count);
    }
    
    /**
     * Compara "count" bytes de los sectores de dos arreglos de bytes, en forma insensitiva.
     *
     * @param m1 Primer arreglo de bytes a utilizar.
     * @param start_m1 Primer byte del primer sector.
     * @param length_m1 Longitud del primer sector.
     * @param m2 Segundo arreglo de bytes a utilizar.
     * @param count Cantidad de bytes a comparar de los dos sectores.
     *
     * @return Devuelve un valor menor que cero (< 0) si el sector de m1 es menor que
     *         que el sector de m2 en "count" bytes; un valor igual a cero (= 0) si
     *         el sector de m1 es igual al sector de m2 en "count" bytes; y un valor
     *         mayor que cero (> 0) si el sector de m1 es mayor que el sector de m2
     *         en "count" bytes.
     */
    public static int memnicmp(final byte[] m1, int start_m1, int length_m1,
            final byte[] m2, int count) {
        return memnicmp(m1, start_m1, length_m1,
                m2, 0, m2.length,
                count);
    }
    
    /**
     * Compara "count" bytes de dos arreglos de bytes, en forma insensitiva.
     *
     * @param m1 Primer arreglo de bytes a utilizar.
     * @param m2 Segundo arreglo de bytes a utilizar.
     * @param count Cantidad de bytes a comparar de los dos arreglos.
     *
     * @return Devuelve un valor menor que cero (< 0) si el arreglo m1 es menor que
     *         que el arreglo m2 en "count" bytes; un valor igual a cero (= 0) si
     *         el arreglo m1 es igual al arreglo m2 en "count" bytes; y un valor
     *         mayor que cero (> 0) si el arreglo m1 es mayor que el arreglo m2
     *         en "count" bytes.
     */
    public static int memnicmp(final byte[] m1, final byte[] m2, int count) {
        return memnicmp(m1, 0, m1.length,
                m2, 0, m2.length,
                count);
    }
    
    /**
     * Compara los sectores de dos arreglos de bytes, en forma insensitiva.
     *
     * @param m1 Primer arreglo de bytes a utilizar.
     * @param start_m1 Primer byte del primer sector.
     * @param length_m1 Longitud del primer sector.
     * @param m2 Segundo arreglo de bytes a utilizar.
     * @param start_m2 Primer byte del sengundo sector.
     * @param length_m2 Longitud del segundo sector.
     *
     * @return Devuelve un valor menor que cero (< 0) si el sector de m1 es menor que
     *         que el sector de m2; un valor igual a cero (= 0) si el sector de m1 es
     *         igual al sector de m2; y un valord mayor que cero (> 0) si el sector
     *         de m1 es mayor que el sector de m2.
     */
    public static int memicmp(final byte[] m1, int start_m1, int length_m1,
            final byte[] m2, int start_m2, int length_m2) {
        // Estabilidad (for dummys)
        // Lo siguiente puede omitirse si el programador es responsable.
        length_m1 = Math.min(length_m1, m1.length - start_m1);
        length_m2 = Math.min(length_m2, m2.length - start_m2);
        // La siguiente condicional es lógica de comparación y no puede
        // omitirse.
        if ((length_m1 > 0) && (length_m2 > 0) && (length_m1 == length_m2)) {
            return _memnicmp(m1, start_m1, length_m1,
                    m2, start_m2, length_m2,
                    length_m1);
        }
        return (length_m1 - length_m2);
    }
    
    /**
     * Compara dos arreglos de bytes, en forma insensitiva.
     *
     * @param m1 Primer arreglo de bytes a utilizar.
     * @param start_m1 Utilizar el primer arreglo desde esta posición.
     * @param m2 Segundo arreglo de bytes a utilizar.
     * @param start_m2 Utilizar el segundo arreglo desde esta posición.
     *
     * @return Devuelve un valor menor que cero (< 0) si el arreglo m1 es menor que
     *         que el arreglo m2; un valor igual a cero (= 0) si el arreglo m1 es
     *         igual al arreglo m2; y un valor mayor que cero (> 0) si el arreglo
     *         m1 es mayor que el arreglo m2.
     */
    public static int memicmp(final byte[] m1, int start_m1,
            final byte[] m2, int start_m2) {
        return memicmp(m1, start_m1, m1.length - start_m1,
                m2, start_m2, m2.length - start_m2);
        
    }
    
    /**
     * Compara dos arreglos de bytes, en forma insensitiva.
     *
     * @param m1 Primer arreglo de bytes a utilizar.
     * @param m2 Segundo arreglo de bytes a utilizar.
     *
     * @return Devuelve un valor menor que cero (< 0) si el arreglo m1 es menor que
     *         que el arreglo m2; un valor igual a cero (= 0) si el arreglo m1 es
     *         igual al arreglo m2; y un valor mayor que cero (> 0) si el arreglo
     *         m1 es mayor que el arreglo m2.
     */
    public static int memicmp(final byte[] m1, final byte[] m2) {
        return memicmp(m1, 0, m1.length,
                m2, 0, m2.length);
        
    }
    
    /**
     * Compara dos cadenas de caracteres, en forma insensitiva.
     *
     * @param s1 Primera cadena a utilizar.
     * @param s2 Segunda cadena a utilizar.
     *
     * @return Devuelve un valor menor que cero (< 0) si la cadena s1 es menor que
     *         que la cadena s2; un valor igual a cero (= 0) si la cedena s1 es
     *         igual que la cadena s2; y un valor mayor que cero (> 0) si la cadena
     *         s1 es mayor que la cadena s2.
     */
    public static int memicmp(final String  s1, final String s2) {
        return memicmp(s1.getBytes(), s2.getBytes());
    }
    
    /**
     * Maximo común divisor de dos números.
     *
     * @param x Primer número.
     * @param y Segundo número
     *
     * @return Devuelve el máximo comun divisor de dos números.
     *         En caso contrario devuelve -1.
     */
    public static int calcMCD(int x, int y) {
        // Algoritmo simple
        int t;
        x = Math.abs(x);
        y = Math.abs(y);
        t = Math.min(x,y);
        while ( (x % t != 0) || (y % t != 0)) {
            --t;
        }
        return t;
        /**
         * Algoritmo recursivo (Euclides) mas eficiente
         * para numeros grandes
         *
         */
        // 	return (!y) ? x : calcMCD(y,x%y);
    }
        
    public static String decoding(byte[] bytes, int start, int count, final String encoding) {
        String newString;
        if (encoding != null) {
            try {
                newString = new String(bytes, start, count, encoding);
            } catch (Exception e) {
                newString = "";
            }
        } else {
            newString = new String(bytes, start, count);
        }
        return newString;
    }
    
    public static String decoding(byte[] bytes, final String encoding) {
        return Utils.decoding(bytes, 0, bytes.length, encoding);
    }
    
    public static byte[] encoding(final String string, final String encoding) {
        byte[] bytes = null;
        if (encoding == null) {
            bytes = string.getBytes();
        } else {
            try {
                bytes = string.getBytes(encoding);
            } catch (Exception e) {
                bytes = "".getBytes();
            }
        }
        return bytes;
    }
    
    public static double strtod(final String string) {
        double ret = 0.0;
        try {
            ret = Double.parseDouble(string);
        } catch (NumberFormatException e) {
            ret = 0.00;
        }
        return ret;
    }
}
